package com.miaohy.demo.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.miaohy.demo.entity.TBasicSeq;
import com.miaohy.demo.entity.TBasicSeqContent;
import com.miaohy.demo.mapper.TBasicSeqContentMapper;
import com.miaohy.demo.mapper.TBasicSeqMapper;
import com.miaohy.demo.service.IBasicSeqService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author jobob
 * @since 2025-02-23
 */
@Slf4j
@Service
public class BasicSeqServiceImpl extends ServiceImpl<TBasicSeqMapper, TBasicSeq> implements IBasicSeqService {


    @Autowired
    TBasicSeqContentMapper basicSeqContentMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String getSeqNumber(String seqCode) {
        return _getSeqNumber(seqCode, 1, null).get(0);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String getSeqNumberParams(String seqCode, Map<String, String> params) {
        return _getSeqNumber(seqCode, 1, params).get(0);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<String> getSeqNumbersParams(String seqCode, Integer num, Map<String, String> params) {
        return _getSeqNumber(seqCode, num, params);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<String> getSeqNumbers(String seqCode, Integer num) {
        return _getSeqNumber(seqCode, num, null);
    }

    private List<String> _getSeqNumber(String seqCode, Integer num, Map<String, String> params) {
        TBasicSeq basicSeq = baseMapper.selectOne(Wrappers.<TBasicSeq>lambdaQuery()
                .eq(TBasicSeq::getSeqCode, seqCode)
                .last("limit 1 for update")
        );
        List<String> result = ListUtil.toList();
        LocalDateTime localDateTime = LocalDateTime.now();

        String changeExpression = basicSeq.getChangeExpression();
        List<String> changeExpressionList = StrUtil.split(changeExpression, "|");
        String calcChangeExpression = changeExpressionList.stream()
                .map(item -> {
                    if (StrUtil.contains(item, "{")) {
                        if (ObjUtil.isNull(params)) {
                            return StrUtil.EMPTY;
                        } else {
                            String paramKey = StrUtil.replace(StrUtil.replace(item, "{", ""), "}", "");
                            return params.getOrDefault(paramKey, StrUtil.EMPTY);
                        }
                    } else if (StrUtil.contains(item, "(")) {
                        return StrUtil.replace(StrUtil.replace(item, "(", ""), ")", "");
                    } else {
                        String str;
                        try {
                            str = localDateTime.format(DateTimeFormatter.ofPattern(item));
                        } catch (Exception ignore) {
                            str = item;
                        }
                        return str;
                    }
                })
                .collect(Collectors.joining(""));

        TBasicSeqContent basicSeqContent = basicSeqContentMapper.selectOne(Wrappers.<TBasicSeqContent>lambdaQuery()
                .eq(TBasicSeqContent::getSeqCode, seqCode)
                .eq(TBasicSeqContent::getChangeExpressionContent, calcChangeExpression)
                .last("limit 1")
        );
        boolean isCreate = Boolean.FALSE;
        for (int i = 0; i < num; i ++) {
            String tmpSeq = StrUtil.EMPTY;
            if (ObjUtil.isNull(basicSeqContent)) {
                basicSeqContent = new TBasicSeqContent();
                basicSeqContent.setSeqCode(seqCode);
                basicSeqContent.setChangeExpressionContent(calcChangeExpression);
                basicSeqContent.setTotalNum(Integer.parseInt(basicSeq.getSeqMin(), basicSeq.getNumberSystem()) + 1);
                // 这个seq_min和seq_max要求与digit位数一致
                tmpSeq = basicSeq.getSeqMin();
                isCreate = Boolean.TRUE;
            } else {
                Integer totalNum = basicSeqContent.getTotalNum();
                tmpSeq = StrUtil.padPre(Integer.toString(totalNum, basicSeq.getNumberSystem()), basicSeq.getDigit(), "0");
                basicSeqContent.setTotalNum(basicSeqContent.getTotalNum() + 1);
            }
            final String seq = tmpSeq;

            String expression = basicSeq.getExpression();

            List<String> expressionList = StrUtil.split(expression, "|");
            List<String> calcExpressionList = expressionList.stream().map(item -> {
                if (StrUtil.contains(item, "{") || StrUtil.contains(item, "[SEQ]")) {
                    if (StrUtil.contains(item, "[SEQ]")) {
                        return seq;
                    } else {
                        if (ObjUtil.isNull(params)) {
                            return StrUtil.EMPTY;
                        } else {
                            String paramKey = StrUtil.replace(StrUtil.replace(item, "{", ""), "}", "");
                            return params.getOrDefault(paramKey, StrUtil.EMPTY);
                        }
                    }
                } else if (StrUtil.contains(item, "(")) {
                    return StrUtil.replace(StrUtil.replace(item, "(", ""), ")", "");
                } else {
                    String str;
                    try {
                        str = localDateTime.format(DateTimeFormatter.ofPattern(item));
                    } catch (Exception ignore) {
                        str = item;
                    }
                    return str;
                }
            }).collect(Collectors.toList());
            result.add(String.join("", calcExpressionList));
        }

        if (BooleanUtil.isFalse(isCreate)) {
            basicSeqContentMapper.update(null, Wrappers.<TBasicSeqContent>lambdaUpdate()
                    .setSql(String.format("total_num = total_num + %d", num))
                    .eq(TBasicSeqContent::getId, basicSeqContent.getId())
            );
        } else {
            basicSeqContentMapper.insert(basicSeqContent);
        }
        return result;
    }
}
